package com.shockweb.client.impl;

import java.util.List;
import java.util.Map;
import java.util.Random;

import com.shockweb.common.International;
import com.shockweb.common.security.Md5;
import com.shockweb.common.serializable.SerializableObject;
import com.shockweb.bridge.OperationDefine;
import com.shockweb.client.Client;
import com.shockweb.client.ClientException;
import com.shockweb.configcenter.data.Req;
import com.shockweb.configcenter.data.ReqGroup;
import com.shockweb.configcenter.data.ReqName;
import com.shockweb.configcenter.data.ReqSync;
import com.shockweb.configcenter.data.ReqValue;
import com.shockweb.common.log.LogManager;

/**
 * 连接到配置中心客户端
 * 
 * @author 彭明华
 * 2018年3月28日 创建
 */
public class ConfigCenterClient extends Client{

	/**
	 * 密码
	 */
	private String secretKey = null;
	
	/**
	 * 设置密码
	 * @param secretKey
	 */
	public void setSecretKey(String secretKey){
		this.secretKey = secretKey;
	}
	
	/**
	 * @see Client#Client()
	 */
	public ConfigCenterClient(){
		super();
	}
	
    /**
     * @see Client#Client(int, int, int, int)
     * @param timeOut
     * @param connectTimeOut
     * @param sleepTime 
     * @param idleStateTime
     */
    public ConfigCenterClient(int timeOut,int connectTimeOut,int sleepTime,int idleStateTime){
    	super(timeOut,connectTimeOut,sleepTime,idleStateTime);
    }
    
    /**
     * @see Client#Client(int, int, int, int)
     * @param timeOut
     * @param connectTimeOut
     * @param sleepTime 
     * @param idleStateTime
     * @param secretKey
     */
    public ConfigCenterClient(int timeOut,int connectTimeOut,int sleepTime,int idleStateTime,String secretKey){
    	super(timeOut,connectTimeOut,sleepTime,idleStateTime);
    	this.secretKey = secretKey;
    }
    
    /**
     * 初始化其他配置中心
     * @param configs
     * @throws ClientException
     */
    public void syncConfig(Map<String,Map<String,String>> configs)throws ClientException {
		if(configs!=null){
	    	ReqSync req = new ReqSync();
	    	req.setConfigs(configs);
	    	req.setTime(System.currentTimeMillis());
	    	req.setSign(getSign(req));
    		send(OperationDefine.REQ_SYNC_CONFIG,req,ReqSync.class);
		}
    }
    
    
    /**
     * 往配置中心放一个值
     * @param group
     * @param name
     * @param value
     * @throws ClientException
     */
	public void putConfig(String group,String name,String value) throws ClientException {
		if(group!=null && name!=null && value!=null){
	    	ReqValue req = new ReqValue();
	    	req.setGroup(group);
	    	req.setName(name);
	    	req.setValue(value);
	    	req.setTime(System.currentTimeMillis());
	    	req.setSign(getSign(req));
    		send(OperationDefine.REQ_PUT_CONFIG,req,ReqValue.class);
		}
    }
 
	
    /**
     * 删除配置中心一个值
     * @param group
     * @param name
     * @throws ClientException
     */
	public void removeConfig(String group,String name) throws ClientException {
		if(group!=null && name!=null){
			ReqName req = new ReqName();
	    	req.setGroup(group);
	    	req.setName(name);
	    	req.setTime(System.currentTimeMillis());
	    	req.setSign(getSign(req));
    		send(OperationDefine.REQ_REMOVE_CONFIG,req,ReqName.class);
		}
    }
	
	/**
	 * 获取签名值
	 * @param req
	 * @return
	 */
	private String getSign(Object req)throws ClientException {
		try {
			return SerializableObject.base64EncodeString(Md5.md5((req.toString() + secretKey).getBytes(International.CHARSET)));
		} catch (Exception e) {
			throw new ClientException("签名错误",e);
		}
	}
	
    /**
     * 获取一个配置
     * @param group
     * @param name
     * @return
     * @throws ClientException
     */
    public String getConfig(String group,String name) throws ClientException {
    	if(group!=null && name!=null){
    		ReqName req = new ReqName();
    		req.setGroup(group);
    		req.setName(name);
    		return (String)send(OperationDefine.REQ_GET_CONFIG, req,ReqName.class);
    	}else{
    		return null;
    	}
    }
    
    /**
     * 清除所有配置
     * @throws ClientException
     */
    public void clear() throws ClientException {
    	Req req = new Req();
    	req.setTime(System.currentTimeMillis());
    	req.setSign(getSign(req));
    	send(OperationDefine.REQ_CLEAR_CONFIG, req,Req.class);
    }
    
    /**
     * 获取所有group定义
     * @return
     * @throws ClientException
     */
    @SuppressWarnings("unchecked")
	public List<String> queryConfigGroup() throws ClientException {
		Req req = new Req();
		req.setTime(System.currentTimeMillis());
		req.setSign(getSign(req));
		return (List<String>)send(OperationDefine.REQ_QUERY_CONFIGGROUP, req,Req.class);
    }
    
    /**
     * 获取某个group下所有name定义
     * @return
     * @throws ClientException
     */
    @SuppressWarnings("unchecked")
	public List<String> queryConfigName(String group) throws ClientException {
    	if(group!=null){
    		ReqGroup req = new ReqGroup();
    		req.setGroup(group);
    		req.setTime(System.currentTimeMillis());
    		req.setSign(getSign(req));
    		return (List<String>)send(OperationDefine.REQ_QUERY_CONFIGNAME, req,ReqGroup.class);
    	}else{
    		return null;
    	}
    }

	/**
	 * 获取一个可用的ConfigCenterClient
	 * @param urls
	 * @return
	 * @throws ClientException
	 */
	public static ConfigCenterClient getConfigCenterClient(String urls)throws ClientException{
		if(urls!=null && urls.split(",")!=null){
			String[] servers = urls.split(",");
			int index = new Random().nextInt(servers.length);
			ConfigCenterClient client = new ConfigCenterClient();
			int start = index;
			while(client==null || !client.isActive()) {
				try{
					client.connect(servers[index]);
				} catch (ClientException e) {
					LogManager.warn(ConfigCenterClient.class,"连接注册服务器失败 Server=" + servers[index]);
				}
				index ++;
				if(index>=servers.length){
					index -= servers.length;
				}
				if(start == index){
					break;
				}
			}
			if(client==null || !client.isActive()){
				throw new ClientException("连接所有注册服务器异常");
			}else{
				return client;
			}
		}else{
			throw new ClientException("无效的url参数，无法创建ConfigCenterClient" );
		}
	}
}
